package org.openscheduler.modules.trigger.support;

import org.openscheduler.modules.trigger.CalendarIntervalScheduleTriggerTemplate;
import org.openscheduler.modules.trigger.CronScheduleTriggerTemplate;
import org.openscheduler.modules.trigger.DailyTimeIntervalScheduleTriggerTemplate;
import org.openscheduler.modules.trigger.SimpleScheduleTriggerTemplate;
import org.quartz.CalendarIntervalScheduleBuilder;
import org.quartz.CalendarIntervalTrigger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DailyTimeIntervalScheduleBuilder;
import org.quartz.DailyTimeIntervalTrigger;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;

/**
 * TODO : misfireInstruction 코드가 맞는지 테스트 케이스가 필요하다.
 * @author allbegray
 *
 */
public class ScheduleBuilderMaker {
	
	public static CalendarIntervalScheduleBuilder builder(CalendarIntervalScheduleTriggerTemplate template) {
		CalendarIntervalScheduleBuilder builder = CalendarIntervalScheduleBuilder.calendarIntervalSchedule();
		
		if (template.getTimezone() != null) {
			builder.inTimeZone(template.getTimezone());
		}
		
		if (template.getPreserveHourOfDay() != null) {
			builder.preserveHourOfDayAcrossDaylightSavings(template.getPreserveHourOfDay());	
		}
		
		if (template.getSkipDay() != null) {
			builder.skipDayIfHourDoesNotExist(template.getSkipDay());
		}
		
		builder.withInterval(template.getTimeInterval(), template.getUnit());
		
//		builder.withIntervalInDays(intervalInDays);
//		builder.withIntervalInHours(intervalInHours);
//		builder.withIntervalInMinutes(intervalInMinutes);
//		builder.withIntervalInMonths(intervalInMonths);
//		builder.withIntervalInSeconds(intervalInSeconds);
//		builder.withIntervalInWeeks(intervalInWeeks);
//		builder.withIntervalInYears(intervalInYears);
		
		if (template.getMisfireInstruction() != null) {
			if (template.getMisfireInstruction() == CalendarIntervalTrigger.MISFIRE_INSTRUCTION_DO_NOTHING) {
				builder.withMisfireHandlingInstructionDoNothing();		
			} else if (template.getMisfireInstruction() == CalendarIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) {
				builder.withMisfireHandlingInstructionFireAndProceed();
			} else if (template.getMisfireInstruction() == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY) {
				builder.withMisfireHandlingInstructionIgnoreMisfires();
			}
		}
		
		return builder;
	}

	public static CronScheduleBuilder builder(CronScheduleTriggerTemplate template) {
		CronScheduleBuilder builder = CronScheduleBuilder.cronSchedule(template.getCronExpression());
		
//		cronScheduleBuilder.atHourAndMinuteOnGivenDaysOfWeek(hour, minute, daysOfWeek);
//		cronScheduleBuilder.dailyAtHourAndMinute(hour, minute);
//		cronScheduleBuilder.monthlyOnDayAndHourAndMinute(dayOfMonth, hour, minute);
//		cronScheduleBuilder.weeklyOnDayAndHourAndMinute(dayOfWeek, hour, minute);
		
		if (template.getTimezone() != null) {
			builder.inTimeZone(template.getTimezone());
		}
		
		if (template.getMisfireInstruction() != null) {
			if (template.getMisfireInstruction() == CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING) {
				builder.withMisfireHandlingInstructionDoNothing();		
			} else if (template.getMisfireInstruction() == CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) {
				builder.withMisfireHandlingInstructionFireAndProceed();
			} else if (template.getMisfireInstruction() == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY) {
				builder.withMisfireHandlingInstructionIgnoreMisfires();
			}
		}
		
		return builder;
	}

	public static DailyTimeIntervalScheduleBuilder builder(DailyTimeIntervalScheduleTriggerTemplate template) {
		DailyTimeIntervalScheduleBuilder builder = DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule();
		
		builder.withInterval(template.getTimeInterval(), template.getUnit());
		
		if (template.getStartTimeOfDay() != null) {
			builder.startingDailyAt(template.getStartTimeOfDay());
		}
		
		if ("endingDailyAt".equals(template.getEndingDailyType())) {
			builder.endingDailyAt(template.getEndTimeOfDay());	
		} else if ("endingDailyAfterCount".equals(template.getEndingDailyType())) {
			builder.endingDailyAfterCount(template.getCount());	
		}
		
		if ("onDaysOfTheWeek".equals(template.getDaysOfWeekType())) {
			builder.onDaysOfTheWeek(template.getOnDaysOfWeek());	
		} else if ("onEveryDay".equals(template.getDaysOfWeekType())) {
			builder.onEveryDay();	
		} else if ("onMondayThroughFriday".equals(template.getDaysOfWeekType())) {
			builder.onMondayThroughFriday();
		} else if ("onSaturdayAndSunday".equals(template.getDaysOfWeekType())) {
			builder.onSaturdayAndSunday();	
		}
		
		if (template.getMisfireInstruction() != null) {
			if (template.getMisfireInstruction() == DailyTimeIntervalTrigger.MISFIRE_INSTRUCTION_DO_NOTHING) {
				builder.withMisfireHandlingInstructionDoNothing();		
			} else if (template.getMisfireInstruction() == CalendarIntervalTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW) {
				builder.withMisfireHandlingInstructionFireAndProceed();
			} else if (template.getMisfireInstruction() == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY) {
				builder.withMisfireHandlingInstructionIgnoreMisfires();
			}
		}
		
		return builder;
	}

	@SuppressWarnings("static-access")
	public static SimpleScheduleBuilder builder(SimpleScheduleTriggerTemplate template) {
		SimpleScheduleBuilder builder = SimpleScheduleBuilder.simpleSchedule();
		
//		아래쪽 coarse-grained 한 메서드를 활용하도록 하자.
//		builder.withIntervalInHours(intervalInHours);
//		builder.withIntervalInMilliseconds(intervalInMillis);
//		builder.withIntervalInMinutes(intervalInMinutes);
//		builder.withIntervalInSeconds(intervalInSeconds);

//		아래쪽 coarse-grained 한 메서드를 활용하도록 하자.
//		builder.withRepeatCount(triggerRepeatCount);
//		builder.repeatForever();
		
		if ("repeatHourlyForever".equals(template.getRepeatType())) {
			if (template.getHours() == null) {
				builder.repeatHourlyForever();	
			} else {
				builder.repeatHourlyForever(template.getHours());	
			}
			
		} else if ("repeatHourlyForTotalCount".equals(template.getRepeatType())) {
			if (template.getHours() == null) {
				builder.repeatHourlyForTotalCount(template.getCount());	
			} else {
				builder.repeatHourlyForTotalCount(template.getCount(), template.getHours());	
			}
			
		} else if ("repeatMinutelyForever".equals(template.getRepeatType())) {
			if (template.getMinutes() == null) {
				builder.repeatMinutelyForever();	
			} else {
				builder.repeatMinutelyForever(template.getMinutes());
			}
			
		} else if ("repeatMinutelyForTotalCount".equals(template.getRepeatType())) {
			if (template.getMinutes() == null) {
				builder.repeatMinutelyForTotalCount(template.getCount());	
			} else {
				builder.repeatMinutelyForTotalCount(template.getCount(), template.getMinutes());
			}
			
		} else if ("repeatSecondlyForever".equals(template.getRepeatType())) {
			if (template.getSeconds() == null) {
				builder.repeatSecondlyForever();	
			} else {
				builder.repeatSecondlyForever(template.getSeconds());	
			}
			
		} else if ("repeatSecondlyForTotalCount".equals(template.getRepeatType())) {
			if (template.getSeconds() == null) {
				builder.repeatSecondlyForTotalCount(template.getCount());	
			} else {
				builder.repeatSecondlyForTotalCount(template.getCount(), template.getSeconds());
			}
			
		} 
		
		if (template.getMisfireInstruction() != null) {
			if (template.getMisfireInstruction() == SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW) {
				builder.withMisfireHandlingInstructionFireNow();		
				
			} else if (template.getMisfireInstruction() == Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY) {
				builder.withMisfireHandlingInstructionIgnoreMisfires();
				
			} else if (template.getMisfireInstruction() == SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT) {
				builder.withMisfireHandlingInstructionNextWithExistingCount();
				
			} else if (template.getMisfireInstruction() == SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT) {
				builder.withMisfireHandlingInstructionNextWithRemainingCount();
				
			} else if (template.getMisfireInstruction() == SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT) {
				builder.withMisfireHandlingInstructionNowWithExistingCount();
				
			} else if (template.getMisfireInstruction() == SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT) {
				builder.withMisfireHandlingInstructionNowWithRemainingCount();
			}
		}
		
		return builder;
	}
}
